﻿using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public enum FlyItemStateType
{
    Parabola,
    Line,
}

public class FlyItem : MonoBehaviour
{
    public static float _flyUnitUpLength = 3.5f;
    
    
    // 直线飞行还是抛物线飞行
    public FlyItemStateType _flyItemState;
    // 目标位置
    public Vector3 _targetPos;
    // 出发点
    public Vector3 _startPos;
    // 速度
    public float _speed = 10;
    // 初始发射角度
    public float _shootAngle = 45f;
    // 到达后的回调
    public Action<FlyItem> _onItemArrivalAction;
    // 目标会飞
    public bool _targetInSky;

    public bool _remoteObjCanFly = false;

    public float _remoteDis;
    public float _remoteFlyLastTime;
    private float _g;
    private Vector3 _remoteSpeedVec3;
    private Vector3 _gravityVec3;
   
    private float _dTime = 0;
    private float _deltaAngle;
    private float _timer;
    private float _remoteDir;
    public float RemoteDir
    {
        get { return _remoteDir; }
        set { _remoteDir = value; }
    }
    private float _fdeltaTime = 0;
    private bool _bfixUpdate = true;


    public void InitParabola(Vector3 startVec3, Vector3 targetVec3, float moveSpeed, float shootAngle, bool targetInSky, Action<FlyItem> onItemArrival,bool fixUpdae = true)
    {
        _flyItemState = FlyItemStateType.Parabola;
        _startPos = startVec3;
        _targetPos = targetVec3;
        _speed = moveSpeed;
        _shootAngle = shootAngle;
        _targetInSky = targetInSky;
        _onItemArrivalAction = onItemArrival;
        _remoteDis = Vector3.Distance(new Vector3(_startPos.x, 0, _startPos.z), new Vector3(_targetPos.x, _targetPos.z));
        float upDis = _remoteDis * Mathf.Tan(_shootAngle * Mathf.Deg2Rad) * 0.5f;
        InitBaseInfo(upDis);
        _g = upDis / _remoteFlyLastTime * (-2f);
        _deltaAngle = _shootAngle / _remoteFlyLastTime * 2f;
        _dTime = 0f;
        _bfixUpdate = fixUpdae;
        _remoteObjCanFly = true;
    }

    public void InitLine(Vector3 startVec3, Vector3 targetVec3, float moveSpeed, bool targetInSky, Action<FlyItem> onItemArrival, bool fixUpdae = true)
    {
        _flyItemState = FlyItemStateType.Line;
        _startPos = startVec3;
        _targetPos = targetVec3;
        _speed = moveSpeed;
        _targetInSky = targetInSky;
        _onItemArrivalAction = onItemArrival;
        _remoteDis = Vector3.Distance(new Vector3(_startPos.x, 0, _startPos.z), new Vector3(_targetPos.x, _targetPos.z));
        InitBaseInfo(0);
        _dTime = 0f;
        _bfixUpdate = fixUpdae;
        _remoteObjCanFly = true;
    }

    private void InitBaseInfo(float upDis)
    {
        this.transform.position = _startPos;
        this.transform.LookAt(_targetPos);
        _remoteDir = this.transform.eulerAngles.y;
        _remoteFlyLastTime = _remoteDis / _speed;
        if (_targetInSky)
        {
            _remoteSpeedVec3 = new Vector3((_targetPos.x - _startPos.x) / _remoteFlyLastTime, (_targetPos.y - _startPos.y + _flyUnitUpLength) / _remoteFlyLastTime + upDis, (_targetPos.z - _startPos.z) / _remoteFlyLastTime);
        }
        else
        {
            _remoteSpeedVec3 = new Vector3((_targetPos.x - _startPos.x) / _remoteFlyLastTime, (_targetPos.y - _startPos.y) / _remoteFlyLastTime + upDis, (_targetPos.z - _startPos.z) / _remoteFlyLastTime);
        }
    }

    void FixedUpdate()
    {
        if (_remoteObjCanFly && _bfixUpdate)
        {
            _dTime += Time.fixedDeltaTime;
            _fdeltaTime = Time.fixedDeltaTime;
            UpPos();
        }
    }

    public void OnUpdate(float deltaTime)
    {
        if (_remoteObjCanFly)
        {
            _dTime += deltaTime;
            _fdeltaTime = deltaTime;
            UpPos(true);
            //transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, transform.eulerAngles.z);
        }
    }

    private void UpPos(bool bEulerAngle = false)
    {
        switch (_flyItemState)
        {
            case FlyItemStateType.Line:
                if (_dTime > _remoteFlyLastTime)
                {
                    _remoteObjCanFly = false;
                    if (_onItemArrivalAction != null)
                    {
                        _onItemArrivalAction(this);
                    }
                }
                else
                {
                    this.transform.Translate((_remoteSpeedVec3) * _fdeltaTime, Space.World);
                    if (bEulerAngle)
                        transform.forward = _remoteSpeedVec3; 
                }
                break;
            case FlyItemStateType.Parabola:
                _gravityVec3.y = _g * _dTime;
                if (_dTime > _remoteFlyLastTime)
                {
                    _remoteObjCanFly = false;
                    if (_onItemArrivalAction != null)
                    {
                        _onItemArrivalAction(this);
                    }
                }
                else
                {
                    this.transform.Translate((_remoteSpeedVec3 + _gravityVec3) * _fdeltaTime, Space.World);
                    this.transform.eulerAngles = new Vector3(-1f * _shootAngle + _fdeltaTime * _deltaAngle, _remoteDir, this.transform.eulerAngles.z);
                    if (bEulerAngle)
                        transform.forward = (_remoteSpeedVec3 + _gravityVec3).normalized;
                }
                break;
        }
    }

}
